import { useState, useEffect, useLayoutEffect, useMemo } from 'react';
import { RenderDropableWidget, useLayouts, getMessage } from '@inbiz/react';
import { useParams } from 'react-router-dom';
import { withSize, SizeMe } from 'react-sizeme';
import { observer } from '@formily/react';
import { getEditor, changeAmin, useInbizRouter, singleTimeOut, debounce, uuid } from '@inbiz/utils';
import { useGetMenuTreeEffect, globalAppInfo, useLayoutSize } from '@inbiz/render';
import { InbizMenuProps } from '@common/InbizMenu/utils';
import { openUrl } from '@common/InbizMenu/service';
import { EdocMenu, windowTimer } from '@common/InbizMenu/common';
import './style.less';
import logo from '@assets/logo.svg'

interface MenuType {
  DataVersionId: string;
  DisplayName: string;
  Icon?: string;
  IsHaveChild: boolean;
  IsHomePage?: boolean;
  IsInternalLink?: boolean;
  IsTopNode?: boolean;
  LinkUrl?: string;
  Route: string;
  JumpRoute: string;
  OutId: string;
  ParentId?: string;
  Sort?: number;
  loadChildList?: any;
  placement?: any;
  inlineCollapsed?: any;
  showLevel: string[];
  jumpChild?: boolean;
  children?: MenuType[];
  menuOnClick?: Function;
  isSelect?: boolean;
  menu: {
    val: MenuType[];
    set: Function;
  };
  style?: any;
  isPre?: boolean;
  level: number;
  visible?: boolean;
  companentLevel: number;
  inbizMenu?: MenuType[];
}

const getCodeAtLength = (MsgContent: string) => {
  let ChartLength = 0;
  const contentStringLength = MsgContent.length;
  let begin = MsgContent.indexOf('</');
  let end = -1;
  if (begin > -1) {
    end = MsgContent.slice(begin).indexOf('>') + begin;
  }
  if (begin > -1 && end > -1 && begin < end) {
    return ChartLength;
  }
  begin = MsgContent.indexOf('<');
  end = -1;
  if (begin > -1) {
    end = MsgContent.slice(begin).indexOf('/>') + begin;
  }
  if (begin > -1 && end > -1 && begin < end) {
    return ChartLength;
  }
  for (let i = 0; i < contentStringLength - 1; i++) {
    if (MsgContent.charCodeAt(i) > 255) {
      ChartLength = ChartLength + 2;
    } else {
      ChartLength = ChartLength + 1;
    }
  }
  return ChartLength;
};

const Horizontal = observer((props: any) => {
  const {
    menuData,
    showlogo,
    logoconfig,
    defaultLogo,
    emit,
    mainmenu,
    jumpChild,
    showLevel,
    viewtype,
  } = props;

  const [sureNum, $sureNum] = useState(0);
  const [refresh, $refresh] = useState('');
  const [pluginSize, $pluginSize] = useState(0);
  const history = useInbizRouter();
  const [layoutSize] = useLayoutSize();
  const topWidth = layoutSize?.top?.width || 0;
  let pluginWidth = pluginSize || 0;
  const logoWidth = showlogo ? 180 : 0;
  const contentWidth = topWidth - pluginWidth - logoWidth;
  let domMenu: any[] = [];
  let moreMenu: MenuType[] = [];
  menuData.val.forEach((item: MenuType, i: number) => {
    if (item.OutId != 'more') {
      if (i < sureNum) {
        domMenu.push(item);
      } else {
        moreMenu.push(item);
      }
    } else {
      domMenu.push(item);
    }
  });

  if (moreMenu.length > 0 && domMenu) {
    domMenu.push({
      DataVersionId: 'more',
      DisplayName: '',
      IsHaveChild: true,
      children: moreMenu,
      OutId: 'more',
      showLevel,
      Icon: JSON.stringify({
        type: 'icon-more1',
      }),
    });
  }

  const change = () => {
    if (typeof contentWidth !== 'number') {
      return null;
    }
    let nameNum = 0;
    let nowSureNum = 0;
    menuData.val.some((item: MenuType, i: number) => {
      const icon = item.Icon ? JSON.parse(item.Icon) : false;
      nameNum = (icon ? icon.type ? 18 : 0 : 0) + nameNum + getCodeAtLength(getMessage(item.DisplayName)) * 15 + (item.IsHaveChild ? 20 : 0) + 52
      nowSureNum = i + 1;
      if (contentWidth < nameNum) {
        nowSureNum = nowSureNum - 1;
        return true;
      }
    });
    $sureNum(nowSureNum);
  };

  useEffect(() => {
    change()
  }, [menuData, contentWidth, refresh])

  useLayoutEffect(() => {
    const updateSize = debounce({
      fn: () => {
        $refresh(uuid(6));
      },
      delay: 100,
    });
    window.addEventListener('resize', updateSize);
    return () => window.removeEventListener('resize', updateSize);
  }, []);

  return (
    <div className={getEditor() ? 'headerContainer' : 'headerContainer view'}>
      <div className="menuContainer">
        <div
          className="logo"
          onClick={() => {
            openUrl(props, history);
          }}
        >
          {showlogo && (
            <img
              src={
                logoconfig ? `${logoconfig.replace('{AppId}', globalAppInfo.AppId)}` : defaultLogo
              }
            />
          )}
        </div>
        <div className="horizontalMenu">
          {/*@ts-ignore */}
          <EdocMenu
            inbiz={props.inbiz}
            menuData={{
              val: domMenu,
              set: menuData.set,
            }}
            moreMenu={moreMenu}
            emit={emit}
            showLevel={showLevel}
            mainmenu={mainmenu}
            jumpChild={jumpChild}
            viewtype={viewtype}
          />
        </div>
      </div>
      <div className="rightBox" style={{ minWidth: getEditor() ? 200 : 'inherit' }}>
        <SizeMe refreshMode={'debounce'}>
          {
            ({ size }) => {
              if (size.width && typeof size.width === 'number') {
                if (getEditor()) {
                  if (size.width < 200) {
                    $pluginSize(200)
                  } else {
                    $pluginSize(size.width)
                  }
                } else {
                  $pluginSize(size.width)
                }
              }
              return <Plugin plugin={props.plugin} >
                <RenderDropableWidget node={props.plugin} pluginName="InbizMenu.Plugin" />
              </Plugin>
            }
          }
        </SizeMe>
      </div>
    </div>
  );
});

export const InbizMenu = (props: InbizMenuProps) => {
  const {
    viewtype,
    showlogo,
    logoconfig,
    shrinkage,
    displaytype,
    menustyle,
    showLevel,
    linkcomponent,
    mainmenu,
    jumpChild,
    plugin,
    isAmin,
    emit,
    url,
    page,
    linkType,
  } = props;

  const requestMenu = useGetMenuTreeEffect();
  const params: any = useParams();

  const [menuData, $menuData] = useState<MenuType[]>([]);

  const defaultLogo = globalAppInfo?.inbizLogo || logo;

  const sendMenuMsg = (menuData: MenuType[]) => {
    menuData.map((item: MenuType) => {
      const pageRouter = params?.pageRouter;
      const oneLevelRoute = pageRouter === 'page' ? params.childRouter : pageRouter;

      if (item?.Route === oneLevelRoute) {
        item.isSelect = true;
        if (!item.JumpRoute) {
          item.JumpRoute = item.Route;
        }
        //暂时处理
        // 只展示1级
        const isSelectOne = showLevel?.length === 1 && showLevel[0] === '1';
        if (props?.emit && isSelectOne) {
          windowTimer({
            fn: () => {
              props?.emit('onvmenu', {
                OutId: item.OutId,
                Route: item.Route,
                JumpRoute: item.JumpRoute,
              });
            },
            time: 200,
          });

        }
      }
    });
  };

  //  初次数据渲染
  useEffect(() => {
    if (!mainmenu && !getEditor()) {
      return;
    }

    if (mainmenu) {
      if (menuData.length > 0 && !getEditor()) {
        sendMenuMsg(menuData);
        return;
      }
      if (showLevel?.length > 0) {
        if (showLevel[0] === '1') {
          requestMenu((res: any) => {
            sendMenuMsg(res);
            $menuData(res);
          });
        } else {
          $menuData([]);
        }
      } else {
        $menuData([]);
      }
    } else {
      $menuData([]);
    }
  }, [mainmenu, showLevel, params]);

  // 用于菜单接收主菜单发的事件
  useEffect(() => {
    if (!mainmenu) {
      props?.inbiz(linkcomponent)?.on('vmenu', (menu: MenuType[]) => {
        windowTimer({
          fn: () => {
            if (Array.isArray(menu)) {
              $menuData(menu);
              return;
            }
            requestMenu((res: MenuType[]) => {
              res = res.map((item) => {
                item.Route = `${menu.JumpRoute}/${item.JumpRoute}`;
                return item;
              });
              $menuData(res);
            }, menu?.OutId);
          },
          time: 100,
        });
      });
    }
  }, [mainmenu]);

  /**
   * 顶级菜单处理函数
   *@data 一级菜单的所有值
   */
  const topHoverChange = (data: MenuType[]) => {
    let newData: MenuType[] = [];
    data.forEach((item: any) => {
      if (item.OutId != 'more') {
        newData.push(item);
      } else {
        newData = newData.concat(item.children);
      }
    });
    $menuData(newData);
  };

  // 菜单参数集
  const menuProps = {
    menuData: {
      val: menuData,
      set: topHoverChange,
    },
    viewtype,
    logoconfig,
    plugin,
    showlogo,
    defaultLogo,
    showLevel,
    displaytype,
    shrinkage,
    mainmenu,
    menustyle,
    jumpChild,
    url,
    page,
    linkType,
    emit,
    inbiz: props.inbiz
  };

  useEffect(() => {
    changeAmin(isAmin);
  }, [isAmin]);
  return (
    <div className={'inbiz-InbizMenu'}>
      <Horizontal {...menuProps} />
    </div>
  );
};

export const Plugin: React.FC<any> = ({ children, ...props }) => {
  const rightBox = useLayouts('InbizMenu.Plugin');
  const isPreview = rightBox && rightBox.length && rightBox.length > 0 && rightBox[0].props;
  const pluginProps = isPreview || props;
  const style = {
    display: 'flex',
    minHeight: 60,
    overflow: 'auto',
    flexDirection: pluginProps.direction || 'row',
    justifyContent: pluginProps.direction == 'row' ? pluginProps.align || 'center' : 'center',
    alignItems: pluginProps.direction !== 'row' ? pluginProps.align || 'center' : 'center',
  };

  const __render = useMemo(() => {
    return <div
      style={{
        ...style,
        ...props.style,
      }}
    >
      {pluginProps && children}
    </div>
  }, [pluginProps, children, style, props.style])

  return __render;
};

InbizMenu.Plugin = Plugin;
export default InbizMenu
